home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / vbrender_old.c < prev    next >
C/C++ Source or Header  |  1999-02-04  |  43KB  |  1,396 lines

  1. /* $Id: vbrender.c,v 3.6 1998/08/06 01:36:38 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: vbrender.c,v $
  26.  * Revision 3.6  1998/08/06 01:36:38  brianp
  27.  * if polygon area is zero and using GL_LINE or GL_POINT mode don't cull it
  28.  *
  29.  * Revision 3.5  1998/06/13 15:23:31  brianp
  30.  * added some new debugging code
  31.  *
  32.  * Revision 3.4  1998/03/27 04:33:33  brianp
  33.  * fixed more G++ warnings
  34.  *
  35.  * Revision 3.3  1998/03/27 04:26:44  brianp
  36.  * fixed G++ warnings
  37.  *
  38.  * Revision 3.2  1998/03/05 03:09:31  brianp
  39.  * added a few assertions in gl_render_vb()
  40.  *
  41.  * Revision 3.1  1998/02/02 03:09:34  brianp
  42.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  43.  *
  44.  * Revision 3.0  1998/01/31 21:06:45  brianp
  45.  * initial rev
  46.  *
  47.  */
  48.  
  49.  
  50. /*
  51.  * Render points, lines, and polygons.  The only entry point to this
  52.  * file is the gl_render_vb() function.  This function is called after
  53.  * the vertex buffer has filled up or glEnd() has been called.
  54.  *
  55.  * This file basically only makes calls to the clipping functions and
  56.  * the point, line and triangle rasterizers via the function pointers.
  57.  *    context->Driver.PointsFunc()
  58.  *    context->Driver.LineFunc()
  59.  *    context->Driver.TriangleFunc()
  60.  */
  61.  
  62.  
  63. #ifdef PC_HEADER
  64. #include "all.h"
  65. #else
  66. #include <stdio.h>
  67. #include "clip.h"
  68. #include "context.h"
  69. #include "light.h"
  70. #include "lines.h"
  71. #include "macros.h"
  72. #include "matrix.h"
  73. #include "pb.h"
  74. #include "points.h"
  75. #include "types.h"
  76. #include "vb.h"
  77. #include "vbrender.h"
  78. #include "xform.h"
  79. #endif
  80.  
  81.  
  82. /*
  83.  * This file implements rendering of points, lines and polygons defined by
  84.  * vertices in the vertex buffer.
  85.  */
  86.  
  87.  
  88.  
  89. #ifdef PROFILE
  90. #  define START_PROFILE                         \
  91.         {                                       \
  92.            GLdouble t0 = gl_time();
  93.  
  94. #  define END_PROFILE( TIMER, COUNTER, INCR )   \
  95.            TIMER += (gl_time() - t0);           \
  96.            COUNTER += INCR;                     \
  97.         }
  98. #else
  99. #  define START_PROFILE
  100. #  define END_PROFILE( TIMER, COUNTER, INCR )
  101. #endif
  102.  
  103.  
  104.  
  105. /*
  106.  * These are called just before the device driver point, line and triangle
  107.  * functions.  It's useful to be able to set breakpoints in these stubs.
  108.  */
  109. #ifdef DEBUG
  110. static void debug_points(void)
  111. {
  112.    ;  /* no-op */
  113. }
  114.  
  115. static void debug_line(void)
  116. {
  117.    ;  /* no-op */
  118. }
  119.  
  120. static void debug_triangle(void)
  121. {
  122.    ;  /* no-op */
  123. }
  124. #endif
  125.  
  126.  
  127.  
  128. /*
  129.  * Render a line segment from VB[v1] to VB[v2] when either one or both
  130.  * endpoints must be clipped.
  131.  */
  132. static void render_clipped_line( GLcontext *ctx, GLuint v1, GLuint v2 )
  133. {
  134.    GLfloat ndc_x, ndc_y, ndc_z;
  135.    GLuint provoking_vertex;
  136.    struct vertex_buffer *VB = ctx->VB;
  137.  
  138.    /* which vertex dictates the color when flat shading: */
  139.    provoking_vertex = v2;
  140.  
  141.    /*
  142.     * Clipping may introduce new vertices.  New vertices will be stored
  143.     * in the vertex buffer arrays starting with location VB->Free.  After
  144.     * we've rendered the line, these extra vertices can be overwritten.
  145.     */
  146.    VB->Free = VB_MAX;
  147.  
  148.    /* Clip against user clipping planes */
  149.    if (ctx->Transform.AnyClip) {
  150.       GLuint orig_v1 = v1, orig_v2 = v2;
  151.       if (gl_userclip_line( ctx, &v1, &v2 )==0)
  152.         return;
  153.       /* Apply projection matrix:  clip = Proj * eye */
  154.       if (v1!=orig_v1) {
  155.          TRANSFORM_POINT( VB->Clip[v1], ctx->ProjectionMatrix, VB->Eye[v1] );
  156.       }
  157.       if (v2!=orig_v2) {
  158.          TRANSFORM_POINT( VB->Clip[v2], ctx->ProjectionMatrix, VB->Eye[v2] );
  159.       }
  160.    }
  161.  
  162.    /* Clip against view volume */
  163.    if (gl_viewclip_line( ctx, &v1, &v2 )==0)
  164.       return;
  165.  
  166.    /* Transform from clip coords to ndc:  ndc = clip / W */
  167.    if (VB->Clip[v1][3] != 0.0F) {
  168.       GLfloat wInv = 1.0F / VB->Clip[v1][3];
  169. #ifndef __PPC__
  170.       ndc_x = VB->Clip[v1][0] * wInv;
  171.       ndc_y = VB->Clip[v1][1] * wInv;
  172. #else
  173.       ndc_x = VB->Clip[v1][0] / VB->Clip[v1][3];
  174.       ndc_y = VB->Clip[v1][1] / VB->Clip[v1][3];
  175. #endif
  176.       ndc_z = VB->Clip[v1][2] * wInv;
  177.    }
  178.    else {
  179.       /* Can't divide by zero, so... */
  180.       ndc_x = ndc_y = ndc_z = 0.0F;
  181.    }
  182.  
  183.    /* Map ndc coord to window coords. */
  184.    VB->Win[v1][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  185.    VB->Win[v1][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  186.    VB->Win[v1][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  187.  
  188.    /* Transform from clip coords to ndc:  ndc = clip / W */
  189.    if (VB->Clip[v2][3] != 0.0F) {
  190.       GLfloat wInv = 1.0F / VB->Clip[v2][3];
  191. #ifndef __PPC__
  192.       ndc_x = VB->Clip[v2][0] * wInv;
  193.       ndc_y = VB->Clip[v2][1] * wInv;
  194. #else
  195.       ndc_x = VB->Clip[v2][0] / VB->Clip[v2][3];
  196.       ndc_y = VB->Clip[v2][1] / VB->Clip[v2][3];
  197. #endif
  198.       ndc_z = VB->Clip[v2][2] * wInv;
  199.    }
  200.    else {
  201.       /* Can't divide by zero, so... */
  202.       ndc_x = ndc_y = ndc_z = 0.0F;
  203.    }
  204.  
  205.    /* Map ndc coord to window coords. */
  206.    VB->Win[v2][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  207.    VB->Win[v2][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  208.    VB->Win[v2][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  209.  
  210.    if (ctx->Driver.RasterSetup) {
  211.       /* Device driver rasterization setup */
  212.       (*ctx->Driver.RasterSetup)( ctx, v1, v1+1 );
  213.       (*ctx->Driver.RasterSetup)( ctx, v2, v2+1 );
  214.    }
  215.  
  216.    START_PROFILE
  217. #ifdef DEBUG
  218.       debug_line();
  219. #endif
  220.    (*ctx->Driver.LineFunc)( ctx, v1, v2, provoking_vertex );
  221.    END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  222. }
  223.  
  224.  
  225.  
  226. /*
  227.  * Compute Z offsets for a polygon with plane defined by (A,B,C,D)
  228.  * D is not needed.
  229.  */
  230. static void offset_polygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c )
  231. {
  232.    GLfloat ac, bc, m;
  233.    GLfloat offset;
  234.  
  235.    if (c<0.001F && c>-0.001F) {
  236.       /* to prevent underflow problems */
  237.       offset = 0.0F;
  238.    }
  239.    else {
  240.       ac = a / c;
  241.       bc = b / c;
  242.       if (ac<0.0F)  ac = -ac;
  243.       if (bc<0.0F)  bc = -bc;
  244.       m = MAX2( ac, bc );
  245.       /* m = sqrt( ac*ac + bc*bc ); */
  246.  
  247.       offset = m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits;
  248.    }
  249.  
  250.    ctx->PointZoffset   = ctx->Polygon.OffsetPoint ? offset : 0.0F;
  251.    ctx->LineZoffset    = ctx->Polygon.OffsetLine  ? offset : 0.0F;
  252.    ctx->PolygonZoffset = ctx->Polygon.OffsetFill  ? offset : 0.0F;
  253. }
  254.  
  255.  
  256.  
  257. /*
  258.  * When glPolygonMode() is used to specify that the front/back rendering
  259.  * mode for polygons is not GL_FILL we end up calling this function.
  260.  */
  261. static void unfilled_polygon( GLcontext *ctx,
  262.                               GLuint n, GLuint vlist[],
  263.                               GLuint pv, GLuint facing )
  264. {
  265.    GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
  266.    struct vertex_buffer *VB = ctx->VB;
  267.  
  268.    if (mode==GL_POINT) {
  269.       GLuint i, j;
  270.       GLboolean edge;
  271.  
  272.       if (!ctx->Driver.PointsFunc)
  273.          gl_set_point_function( ctx );
  274.  
  275.       if (   ctx->Primitive==GL_TRIANGLES
  276.           || ctx->Primitive==GL_QUADS
  277.           || ctx->Primitive==GL_POLYGON) {
  278.          edge = GL_FALSE;
  279.       }
  280.       else {
  281.          edge = GL_TRUE;
  282.       }
  283.  
  284.       for (i=0;i<n;i++) {
  285.          j = vlist[i];
  286.          if (edge || VB->Edgeflag[j]) {
  287. #ifdef DEBUG
  288.             debug_points();
  289. #endif
  290.             (*ctx->Driver.PointsFunc)( ctx, j, j );
  291.          }
  292.       }
  293.    }
  294.    else if (mode==GL_LINE) {
  295.       GLuint i, j0, j1;
  296.       GLboolean edge;
  297.  
  298.       if (!ctx->Driver.LineFunc)
  299.          gl_set_line_function( ctx );
  300.  
  301.       ctx->StippleCounter = 0;
  302.  
  303.       if (   ctx->Primitive==GL_TRIANGLES
  304.           || ctx->Primitive==GL_QUADS
  305.           || ctx->Primitive==GL_POLYGON) {
  306.          edge = GL_FALSE;
  307.       }
  308.       else {
  309.          edge = GL_TRUE;
  310.       }
  311.  
  312.       /* draw the edges */
  313.       for (i=0;i<n;i++) {
  314.          j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  315.          j1 = vlist[i];
  316.          if (edge || VB->Edgeflag[j0]) {
  317.             START_PROFILE
  318. #ifdef DEBUG
  319.       debug_line();
  320. #endif
  321.             (*ctx->Driver.LineFunc)( ctx, j0, j1, pv );
  322.             END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  323.          }
  324.       }
  325.    }
  326.    else {
  327.       /* Fill the polygon */
  328.       GLuint j0, i;
  329.       j0 = vlist[0];
  330.       for (i=2;i<n;i++) {
  331.          START_PROFILE
  332. #ifdef DEBUG
  333.          debug_triangle();
  334. #endif
  335.          (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  336.          END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  337.       }
  338.    }
  339. }
  340.  
  341.  
  342. /*
  343.  * Compute signed area of the n-sided polgyon specified by vertices vb->Win[]
  344.  * and vertex list vlist[].
  345.  * A clockwise polygon will return a negative area.
  346.  * A counter-clockwise polygon will return a positive area.
  347.  */
  348. static GLfloat polygon_area( const struct vertex_buffer *vb,
  349.                              GLuint n, const GLuint vlist[] )
  350. {
  351.    GLfloat area = 0.0F;
  352.    GLuint i;
  353.    for (i=0;i<n;i++) {
  354.       /* area = sum of trapezoids */
  355.       GLuint j0 = vlist[i];
  356.       GLuint j1 = vlist[(i+1)%n];
  357.       GLfloat x0 = vb->Win[j0][0];
  358.       GLfloat y0 = vb->Win[j0][1];
  359.       GLfloat x1 = vb->Win[j1][0];
  360.       GLfloat y1 = vb->Win[j1][1];
  361.       GLfloat trapArea = (x0-x1)*(y0+y1);  /* Note: no divide by two here! */
  362.       area += trapArea;
  363.    }
  364.    return area * 0.5F;     /* divide by two now! */
  365. }
  366.  
  367.  
  368. /*
  369.  * Render a polygon in which doesn't have to be clipped.
  370.  * Input:  n - number of vertices
  371.  *         vlist - list of vertices in the polygon.
  372.  */
  373. static void render_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
  374. {
  375.    struct vertex_buffer *VB = ctx->VB;
  376.    GLuint pv;
  377.  
  378.    /* which vertex dictates the color when flat shading: */
  379.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  380.  
  381.    /* Compute orientation of polygon, do cull test, offset, etc */
  382.    {
  383.       GLuint facing;   /* 0=front, 1=back */
  384.       GLfloat area = polygon_area( VB, n, vlist );
  385.  
  386.       if (area==0.0F && !ctx->Polygon.Unfilled) {
  387.          /* polygon has zero area, don't draw it */
  388.          return;
  389.       }
  390.  
  391.       facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  392.  
  393.       if ((facing+1) & ctx->Polygon.CullBits) {
  394.          return;   /* culled */
  395.       }
  396.  
  397.       if (ctx->Polygon.OffsetAny) {
  398.          /* compute plane equation of polygon, apply offset */
  399.          GLuint j0 = vlist[0];
  400.          GLuint j1 = vlist[1];
  401.          GLuint j2 = vlist[2];
  402.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  403.          GLfloat ex = VB->Win[j1][0] - VB->Win[j3][0];
  404.          GLfloat ey = VB->Win[j1][1] - VB->Win[j3][1];
  405.          GLfloat ez = VB->Win[j1][2] - VB->Win[j3][2];
  406.          GLfloat fx = VB->Win[j2][0] - VB->Win[j0][0];
  407.          GLfloat fy = VB->Win[j2][1] - VB->Win[j0][1];
  408.          GLfloat fz = VB->Win[j2][2] - VB->Win[j0][2];
  409.          GLfloat a = ey*fz-ez*fy;
  410.          GLfloat b = ez*fx-ex*fz;
  411.          GLfloat c = ex*fy-ey*fx;
  412.          offset_polygon( ctx, a, b, c );
  413.       }
  414.  
  415.       if (ctx->LightTwoSide) {
  416.          if (facing==1) {
  417.             /* use back color or index */
  418.             VB->Color = VB->Bcolor;
  419.             VB->Index = VB->Bindex;
  420.             VB->Specular = VB->Bspec;
  421.          }
  422.          else {
  423.             /* use front color or index */
  424.             VB->Color = VB->Fcolor;
  425.             VB->Index = VB->Findex;
  426.             VB->Specular = VB->Fspec;
  427.          }
  428.       }
  429.  
  430.       /* Render the polygon! */
  431.       if (ctx->Polygon.Unfilled) {
  432.          unfilled_polygon( ctx, n, vlist, pv, facing );
  433.       }
  434.       else {
  435.          /* Draw filled polygon as a triangle fan */
  436.          GLuint i;
  437.          GLuint j0 = vlist[0];
  438.          for (i=2;i<n;i++) {
  439.             START_PROFILE
  440. #ifdef DEBUG
  441.             debug_triangle();
  442. #endif
  443.             (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  444.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  445.          }
  446.       }
  447.    }
  448. }
  449.  
  450.  
  451.  
  452. /*
  453.  * Render a polygon in which at least one vertex has to be clipped.
  454.  * Input:  n - number of vertices
  455.  *         vlist - list of vertices in the polygon.
  456.  *                 CCW order = front facing.
  457.  */
  458. static void render_clipped_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
  459. {
  460.    GLuint pv;
  461.    struct vertex_buffer *VB = ctx->VB;
  462.    GLfloat (*win)[3] = VB->Win;
  463.  
  464.    /* which vertex dictates the color when flat shading: */
  465.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  466.  
  467.    /*
  468.     * Clipping may introduce new vertices.  New vertices will be stored
  469.     * in the vertex buffer arrays starting with location VB->Free.  After
  470.     * we've rendered the polygon, these extra vertices can be overwritten.
  471.     */
  472.    VB->Free = VB_MAX;
  473.  
  474.    /* Clip against user clipping planes in eye coord space. */
  475.    if (ctx->Transform.AnyClip) {
  476.       GLfloat *proj = ctx->ProjectionMatrix;
  477.       GLuint i;
  478.       n = gl_userclip_polygon( ctx, n, vlist );
  479.       if (n<3)
  480.          return;
  481.       /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */
  482.       for (i=0;i<n;i++) {
  483.          GLuint j = vlist[i];
  484.          TRANSFORM_POINT( VB->Clip[j], proj, VB->Eye[j] );
  485.       }
  486.    }
  487.  
  488.    /* Clip against view volume in clip coord space */
  489.    n = gl_viewclip_polygon( ctx, n, vlist );
  490.    if (n<3)
  491.       return;
  492.  
  493.    /* Transform new vertices from clip to ndc to window coords.    */
  494.    /* ndc = clip / W    window = viewport_mapping(ndc)             */
  495.    /* Note that window Z values are scaled to the range of integer */
  496.    /* depth buffer values.                                         */
  497.    {
  498.       GLfloat sx = ctx->Viewport.Sx;
  499.       GLfloat tx = ctx->Viewport.Tx;
  500.       GLfloat sy = ctx->Viewport.Sy;
  501.       GLfloat ty = ctx->Viewport.Ty;
  502.       GLfloat sz = ctx->Viewport.Sz;
  503.       GLfloat tz = ctx->Viewport.Tz;
  504.       GLuint i;
  505.       /* Only need to compute window coords for new vertices */
  506.       for (i=VB_MAX; i<VB->Free; i++) {
  507.          if (VB->Clip[i][3] != 0.0F) {
  508.             GLfloat wInv = 1.0F / VB->Clip[i][3];
  509. #ifndef __PPC__
  510.             win[i][0] = VB->Clip[i][0] * wInv * sx + tx;
  511.             win[i][1] = VB->Clip[i][1] * wInv * sy + ty;
  512. #else
  513.             win[i][0] = (VB->Clip[i][0] /VB->Clip[i][3]) * sx + tx;
  514.             win[i][1] = (VB->Clip[i][1] /VB->Clip[i][3]) * sy + ty;
  515. #endif
  516.             win[i][2] = VB->Clip[i][2] * wInv * sz + tz;
  517.          }
  518.          else {
  519.             /* Can't divide by zero, so... */
  520.             win[i][0] = win[i][1] = win[i][2] = 0.0F;
  521.          }
  522.       }
  523.       if (ctx->Driver.RasterSetup && (VB->Free > VB_MAX)) {
  524.          /* Device driver raster setup for newly introduced vertices */
  525.          (*ctx->Driver.RasterSetup)(ctx, VB_MAX, VB->Free);
  526.       }
  527.  
  528. #ifdef DEBUG
  529.       {
  530.          GLuint i, j;
  531.          for (i=0;i<n;i++) {
  532.             j = vlist[i];
  533.             if (VB->ClipMask[j]) {
  534.                /* Uh oh!  There should be no clip bits set in final polygon! */
  535.                GLuint k, l;
  536.                printf("CLIPMASK %d %d %02x\n", (int)i, (int)j, VB->ClipMask[j]);
  537.                printf("%f %f %f %f\n", VB->Eye[j][0], VB->Eye[j][1], 
  538.                       VB->Eye[j][2], VB->Eye[j][3]);
  539.                printf("%f %f %f %f\n", VB->Clip[j][0], VB->Clip[j][1], 
  540.                       VB->Clip[j][2], VB->Clip[j][3]);
  541.                for (k=0;k<n;k++) {
  542.                   l = vlist[k];
  543.                   printf("%d %d %02x\n", k, l, VB->ClipMask[l]);
  544.                }
  545.             }
  546.          }
  547.       }
  548. #endif
  549.    }
  550.  
  551.    /* Compute orientation of polygon, do cull test, offset, etc */
  552.    {
  553.       GLuint facing;   /* 0=front, 1=back */
  554.       GLfloat area = polygon_area( VB, n, vlist );
  555.  
  556.       if (area==0.0F && !ctx->Polygon.Unfilled) {
  557.          /* polygon has zero area, don't draw it */
  558.          return;
  559.       }
  560.  
  561.       facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  562.  
  563.       if ((facing+1) & ctx->Polygon.CullBits) {
  564.          return;   /* culled */
  565.       }
  566.  
  567.       if (ctx->Polygon.OffsetAny) {
  568.          /* compute plane equation of polygon, apply offset */
  569.          GLuint j0 = vlist[0];
  570.          GLuint j1 = vlist[1];
  571.          GLuint j2 = vlist[2];
  572.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  573.          GLfloat ex = win[j1][0] - win[j3][0];
  574.          GLfloat ey = win[j1][1] - win[j3][1];
  575.          GLfloat ez = win[j1][2] - win[j3][2];
  576.          GLfloat fx = win[j2][0] - win[j0][0];
  577.          GLfloat fy = win[j2][1] - win[j0][1];
  578.          GLfloat fz = win[j2][2] - win[j0][2];
  579.          GLfloat a = ey*fz-ez*fy;
  580.          GLfloat b = ez*fx-ex*fz;
  581.          GLfloat c = ex*fy-ey*fx;
  582.          offset_polygon( ctx, a, b, c );
  583.       }
  584.  
  585.       if (ctx->LightTwoSide) {
  586.          if (facing==1) {
  587.             /* use back color or index */
  588.             VB->Color = VB->Bcolor;
  589.             VB->Index = VB->Bindex;
  590.             VB->Specular = VB->Bspec;
  591.          }
  592.          else {
  593.             /* use front color or index */
  594.             VB->Color = VB->Fcolor;
  595.             VB->Index = VB->Findex;
  596.             VB->Specular = VB->Fspec;
  597.          }
  598.       }
  599.  
  600.       /* Render the polygon! */
  601.       if (ctx->Polygon.Unfilled) {
  602.          unfilled_polygon( ctx, n, vlist, pv, facing );
  603.       }
  604.       else {
  605.          /* Draw filled polygon as a triangle fan */
  606.          GLuint i;
  607.          GLuint j0 = vlist[0];
  608.          for (i=2;i<n;i++) {
  609.             START_PROFILE
  610. #ifdef DEBUG
  611.             debug_triangle();
  612. #endif
  613.             (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  614.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  615.          }
  616.       }
  617.    }
  618. }
  619.  
  620.  
  621.  
  622. /*
  623.  * Render an un-clipped triangle.
  624.  * v0, v1, v2 - vertex indexes.  CCW order = front facing
  625.  * pv - provoking vertex
  626.  */
  627. static void render_triangle( GLcontext *ctx,
  628.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  629. {
  630.    struct vertex_buffer *VB = ctx->VB;
  631.    GLfloat ex, ey, fx, fy, c;
  632.    GLuint facing;  /* 0=front, 1=back */
  633.    GLfloat (*win)[3] = VB->Win;
  634.  
  635.    /* Compute orientation of triangle */
  636.    ex = win[v1][0] - win[v0][0];
  637.    ey = win[v1][1] - win[v0][1];
  638.    fx = win[v2][0] - win[v0][0];
  639.    fy = win[v2][1] - win[v0][1];
  640.    c = ex*fy-ey*fx;
  641.  
  642.    if (c==0.0F && !ctx->Polygon.Unfilled) {
  643.       /* polygon is perpindicular to view plane, don't draw it */
  644.       return;
  645.    }
  646.  
  647.    facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  648.  
  649.    if ((facing+1) & ctx->Polygon.CullBits) {
  650.       return;   /* culled */
  651.    }
  652.  
  653.    if (ctx->Polygon.OffsetAny) {
  654.       /* finish computing plane equation of polygon, compute offset */
  655.       GLfloat fz = win[v2][2] - win[v0][2];
  656.       GLfloat ez = win[v1][2] - win[v0][2];
  657.       GLfloat a = ey*fz-ez*fy;
  658.       GLfloat b = ez*fx-ex*fz;
  659.       offset_polygon( ctx, a, b, c );
  660.    }
  661.  
  662.    if (ctx->LightTwoSide) {
  663.       if (facing==1) {
  664.          /* use back color or index */
  665.          VB->Color = VB->Bcolor;
  666.          VB->Index = VB->Bindex;
  667.          VB->Specular = VB->Bspec;
  668.       }
  669.       else {
  670.          /* use front color or index */
  671.          VB->Color = VB->Fcolor;
  672.          VB->Index = VB->Findex;
  673.          VB->Specular = VB->Fspec;
  674.       }
  675.    }
  676.  
  677.    if (ctx->Polygon.Unfilled) {
  678.       GLuint vlist[3];
  679.       vlist[0] = v0;
  680.       vlist[1] = v1;
  681.       vlist[2] = v2;
  682.       unfilled_polygon( ctx, 3, vlist, pv, facing );
  683.    }
  684.    else {
  685.       START_PROFILE
  686. #ifdef DEBUG
  687.       debug_triangle();
  688. #endif
  689.       (*ctx->Driver.TriangleFunc)( ctx, v0, v1, v2, pv );
  690.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  691.    }
  692. }
  693.  
  694.  
  695.  
  696. /*
  697.  * Render an un-clipped quadrilateral.
  698.  * v0, v1, v2, v3 : CCW order = front facing
  699.  * pv - provoking vertex
  700.  */
  701. static void render_quad( GLcontext *ctx, GLuint v0, GLuint v1,
  702.                          GLuint v2, GLuint v3, GLuint pv )
  703. {
  704.    struct vertex_buffer *VB = ctx->VB;
  705.    GLfloat ex, ey, fx, fy, c;
  706.    GLuint facing;  /* 0=front, 1=back */
  707.    GLfloat (*win)[3] = VB->Win;
  708.  
  709.    /* Compute polygon orientation */
  710.    ex = win[v2][0] - win[v0][0];
  711.    ey = win[v2][1] - win[v0][1];
  712.    fx = win[v3][0] - win[v1][0];
  713.    fy = win[v3][1] - win[v1][1];
  714.    c = ex*fy-ey*fx;
  715.  
  716.    if (c==0.0F && !ctx->Polygon.Unfilled) {
  717.       /* polygon is perpindicular to view plane, don't draw it */
  718.       return;
  719.    }
  720.  
  721.    facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  722.  
  723.    if ((facing+1) & ctx->Polygon.CullBits) {
  724.       return;   /* culled */
  725.    }
  726.  
  727.    if (ctx->Polygon.OffsetAny) {
  728.       /* finish computing plane equation of polygon, compute offset */
  729.       GLfloat ez = win[v2][2] - win[v0][2];
  730.       GLfloat fz = win[v3][2] - win[v1][2];
  731.       GLfloat a = ey*fz-ez*fy;
  732.       GLfloat b = ez*fx-ex*fz;
  733.       offset_polygon( ctx, a, b, c );
  734.    }
  735.  
  736.    if (ctx->LightTwoSide) {
  737.       if (facing==1) {
  738.          /* use back color or index */
  739.          VB->Color = VB->Bcolor;
  740.          VB->Index = VB->Bindex;
  741.          VB->Specular = VB->Bspec;
  742.       }
  743.       else {
  744.          /* use front color or index */
  745.          VB->Color = VB->Fcolor;
  746.          VB->Index = VB->Findex;
  747.          VB->Specular = VB->Fspec;
  748.       }
  749.    }
  750.  
  751.    /* Render the quad! */
  752.    if (ctx->Polygon.Unfilled) {
  753.       GLuint vlist[4];
  754.       vlist[0] = v0;
  755.       vlist[1] = v1;
  756.       vlist[2] = v2;
  757.       vlist[3] = v3;
  758.       unfilled_polygon( ctx, 4, vlist, pv, facing );
  759.    }
  760.    else {
  761.       START_PROFILE
  762.       (*ctx->Driver.QuadFunc)( ctx, v0, v1, v2, v3, pv );
  763.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  764.    }
  765. }
  766.  
  767.  
  768.  
  769. /*
  770.  * When the vertex buffer is full, we transform/render it.  Sometimes we
  771.  * have to copy the last vertex (or two) to the front of the vertex list
  772.  * to "continue" the primitive.  For example:  line or triangle strips.
  773.  * This function is a helper for that.
  774.  */
  775. static void copy_vertex( struct vertex_buffer *vb, GLuint dst, GLuint src )
  776. {
  777.    COPY_4V( vb->Clip[dst], vb->Clip[src] );
  778.    COPY_4V( vb->Eye[dst], vb->Eye[src] );
  779.    COPY_3V( vb->Win[dst], vb->Win[src] );
  780.    COPY_4V( vb->Fcolor[dst], vb->Fcolor[src] );
  781.    COPY_4V( vb->Bcolor[dst], vb->Bcolor[src] );
  782.    /* XXX Specular */
  783.    COPY_4V( vb->TexCoord[dst], vb->TexCoord[src] );
  784.    vb->Findex[dst] = vb->Findex[src];
  785.    vb->Bindex[dst] = vb->Bindex[src];
  786.    vb->Edgeflag[dst] = vb->Edgeflag[src];
  787.    vb->ClipMask[dst] = vb->ClipMask[src];
  788.    vb->MaterialMask[dst] = vb->MaterialMask[src];
  789.    vb->Material[dst][0] = vb->Material[src][0];
  790.    vb->Material[dst][1] = vb->Material[src][1];
  791. }
  792.  
  793.  
  794.  
  795.  
  796. /*
  797.  * Either the vertex buffer is full (VB->Count==VB_MAX) or glEnd() has been
  798.  * called.  Render the primitives defined by the vertices and reset the
  799.  * buffer.
  800.  *
  801.  * This function won't be called if the device driver implements a
  802.  * RenderVB() function.  If the device driver renders the vertex buffer
  803.  * then the driver must also call gl_reset_vb()!
  804.  *
  805.  * Input:  allDone - GL_TRUE = caller is glEnd()
  806.  *                   GL_FALSE = calling because buffer is full.
  807.  */
  808. void gl_render_vb( GLcontext *ctx, GLboolean allDone )
  809. {
  810.    struct vertex_buffer *VB = ctx->VB;
  811.    GLuint vlist[VB_SIZE];
  812.  
  813.    switch (ctx->Primitive) {
  814.       case GL_POINTS:
  815.          ASSERT(ctx->Driver.PointsFunc);
  816.          START_PROFILE
  817. #ifdef DEBUG
  818.             debug_points();
  819. #endif
  820.          (*ctx->Driver.PointsFunc)( ctx, 0, VB->Count-1 );
  821.          END_PROFILE( ctx->PointTime, ctx->PointCount, VB->Count )
  822.          break;
  823.  
  824.       case GL_LINES:
  825.          ASSERT(ctx->Driver.LineFunc);
  826.          if (VB->ClipOrMask) {
  827.             GLuint i;
  828.             for (i=1;i<VB->Count;i+=2) {
  829.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  830.                   render_clipped_line( ctx, i-1, i );
  831.                }
  832.                else {
  833.                   START_PROFILE
  834. #ifdef DEBUG
  835.                   debug_line();
  836. #endif
  837.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  838.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  839.                }
  840.                ctx->StippleCounter = 0;
  841.             }
  842.          }
  843.          else {
  844.             GLuint i;
  845.             for (i=1;i<VB->Count;i+=2) {
  846.                START_PROFILE
  847. #ifdef DEBUG
  848.                debug_line();
  849. #endif
  850.                (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  851.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  852.                ctx->StippleCounter = 0;
  853.             }
  854.          }
  855.          break;
  856.  
  857.       case GL_LINE_STRIP:
  858.          ASSERT(ctx->Driver.LineFunc);
  859.          if (VB->ClipOrMask) {
  860.             GLuint i;
  861.             for (i=1;i<VB->Count;i++) {
  862.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  863.                   render_clipped_line( ctx, i-1, i );
  864.                }
  865.                else {
  866.                   START_PROFILE
  867. #ifdef DEBUG
  868.                   debug_line();
  869. #endif
  870.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  871.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  872.                }
  873.             }
  874.          }
  875.          else {
  876.             /* no clipping needed */
  877.             GLuint i;
  878.             for (i=1;i<VB->Count;i++) {
  879.                START_PROFILE
  880. #ifdef DEBUG
  881.                debug_line();
  882. #endif
  883.                (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  884.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  885.             }
  886.          }
  887.          break;
  888.  
  889.       case GL_LINE_LOOP:
  890.          ASSERT(ctx->Driver.LineFunc);
  891.          {
  892.             GLuint i;
  893.             if (VB->Start==0) {
  894.                i = 1;  /* start at 0th vertex */
  895.             }
  896.             else {
  897.                i = 2;  /* skip first vertex, we're saving it until glEnd */
  898.             }
  899.             while (i<VB->Count) {
  900.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  901.                   render_clipped_line( ctx, i-1, i );
  902.                }
  903.                else {
  904.                   START_PROFILE
  905. #ifdef DEBUG
  906.                   debug_line();
  907. #endif
  908.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  909.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  910.                }
  911.                i++;
  912.             }
  913.          }
  914.          break;
  915.  
  916.       case GL_TRIANGLES:
  917.          ASSERT(ctx->Driver.TriangleFunc);
  918.          if (VB->ClipOrMask) {
  919.             GLuint i;
  920.             for (i=2;i<VB->Count;i+=3) {
  921.                if (VB->ClipMask[i-2] & VB->ClipMask[i-1]
  922.                    & VB->ClipMask[i] & CLIP_ALL_BITS) {
  923.                   /* all points clipped by common plane */
  924.                   continue;
  925.                }
  926.                else if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  927.                   vlist[0] = i-2;
  928.                   vlist[1] = i-1;
  929.                   vlist[2] = i-0;
  930.                   render_clipped_polygon( ctx, 3, vlist );
  931.                }
  932.                else {
  933.                   if (ctx->DirectTriangles) {
  934.                      START_PROFILE
  935. #ifdef DEBUG
  936.                      debug_triangle();
  937. #endif
  938.                      (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  939.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  940.                   }
  941.                   else {
  942.                      render_triangle( ctx, i-2, i-1, i, i );
  943.                   }
  944.                }
  945.             }
  946.          }
  947.          else {
  948.             /* no clipping needed */
  949.             GLuint i;
  950.             if (ctx->DirectTriangles) {
  951.                for (i=2;i<VB->Count;i+=3) {
  952.                   START_PROFILE
  953. #ifdef DEBUG
  954.                   debug_triangle();
  955. #endif
  956.                   (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  957.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  958.                }
  959.             }
  960.             else {
  961.                for (i=2;i<VB->Count;i+=3) {
  962.                   render_triangle( ctx, i-2, i-1, i, i );
  963.                }
  964.             }
  965.          }
  966.          break;
  967.  
  968.       case GL_TRIANGLE_STRIP:
  969.          ASSERT(ctx->Driver.TriangleFunc);
  970.          if (VB->ClipOrMask) {
  971.             GLuint i;
  972.             for (i=2;i<VB->Count;i++) {
  973.                if (VB->ClipMask[i-2] & VB->ClipMask[i-1]
  974.                    & VB->ClipMask[i] & CLIP_ALL_BITS) {
  975.                   /* all points clipped by common plane */
  976.                   continue;
  977.                }
  978.                else if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  979.                   if (i&1) {
  980.                      /* reverse vertex order */
  981.                      vlist[0] = i-1;
  982.                      vlist[1] = i-2;
  983.                      vlist[2] = i-0;
  984.                      render_clipped_polygon( ctx, 3, vlist );
  985.                   }
  986.                   else {
  987.                      vlist[0] = i-2;
  988.                      vlist[1] = i-1;
  989.                      vlist[2] = i-0;
  990.                      render_clipped_polygon( ctx, 3, vlist );
  991.                   }
  992.                }
  993.                else {
  994.                   if (ctx->DirectTriangles) {
  995.                      START_PROFILE
  996. #ifdef DEBUG
  997.                      debug_triangle();
  998. #endif
  999.                      (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  1000.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  1001.                   }
  1002.                   else {
  1003.                      if (i&1)
  1004.                         render_triangle( ctx, i, i-1, i-2, i );
  1005.                      else
  1006.                         render_triangle( ctx, i-2, i-1, i, i );
  1007.                   }
  1008.                }
  1009.             }
  1010.          }
  1011.          else {
  1012.             /* no vertices were clipped */
  1013.             GLuint i;
  1014.             if (ctx->DirectTriangles) {
  1015.                for (i=2;i<VB->Count;i++) {
  1016.                   START_PROFILE
  1017. #ifdef DEBUG
  1018.                   debug_triangle();
  1019. #endif
  1020.                   (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  1021.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  1022.                }
  1023.             }
  1024.             else {
  1025.                for (i=2;i<VB->Count;i++) {
  1026.                   if (i&1)
  1027.                      render_triangle( ctx, i, i-1, i-2, i );
  1028.                   else
  1029.                      render_triangle( ctx, i-2, i-1, i, i );
  1030.                }
  1031.             }
  1032.          }
  1033.          break;
  1034.  
  1035.       case GL_TRIANGLE_FAN:
  1036.          ASSERT(ctx->Driver.TriangleFunc);
  1037.          if (VB->ClipOrMask) {
  1038.             GLuint i;
  1039.             for (i=2;i<VB->Count;i++) {
  1040.                if (VB->ClipMask[0] & VB->ClipMask[i-1] & VB->ClipMask[i]
  1041.                    & CLIP_ALL_BITS) {
  1042.                   /* all points clipped by common plane */
  1043.                   continue;
  1044.                }
  1045.                else if (VB->ClipMask[0] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  1046.                   vlist[0] = 0;
  1047.                   vlist[1] = i-1;
  1048.                   vlist[2] = i;
  1049.                   render_clipped_polygon( ctx, 3, vlist );
  1050.                }
  1051.                else {
  1052.                   if (ctx->DirectTriangles) {
  1053.                      START_PROFILE
  1054. #ifdef DEBUG
  1055.                      debug_triangle();
  1056. #endif
  1057.                      (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i );
  1058.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  1059.                   }
  1060.                   else {
  1061.                      render_triangle( ctx, 0, i-1, i, i );
  1062.                   }
  1063.                }
  1064.             }
  1065.          }
  1066.          else {
  1067.             /* no clipping needed */
  1068.             GLuint i;
  1069.             if (ctx->DirectTriangles) {
  1070.                for (i=2;i<VB->Count;i++) {
  1071.                   START_PROFILE
  1072. #ifdef DEBUG
  1073.                   debug_triangle();
  1074. #endif
  1075.                   (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i );
  1076.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  1077.                }
  1078.             }
  1079.             else {
  1080.                for (i=2;i<VB->Count;i++) {
  1081.                   render_triangle( ctx, 0, i-1, i, i );
  1082.                }
  1083.             }
  1084.          }
  1085.          break;
  1086.  
  1087.       case GL_QUADS:
  1088.          ASSERT(ctx->Driver.TriangleFunc);
  1089.          ASSERT(ctx->Driver.QuadFunc);
  1090.          if (VB->ClipOrMask) {
  1091.             GLuint i;
  1092.             for (i=3;i<VB->Count;i+=4) {
  1093.                if (VB->ClipMask[i-3] & VB->ClipMask[i-2]
  1094.                    & VB->ClipMask[i-1] & VB->ClipMask[i] & CLIP_ALL_BITS) {
  1095.                   /* all points clipped by common plane */
  1096.                   continue;
  1097.                }
  1098.                else if (VB->ClipMask[i-3] | VB->ClipMask[i-2]
  1099.                         | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  1100.                   vlist[0] = i-3;
  1101.                   vlist[1] = i-2;
  1102.                   vlist[2] = i-1;
  1103.                   vlist[3] = i-0;
  1104.                   render_clipped_polygon( ctx, 4, vlist );
  1105.                }
  1106.                else {
  1107.                   if (ctx->DirectTriangles) {
  1108.                      START_PROFILE
  1109.                      (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i );
  1110.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1111.                   }
  1112.                   else {
  1113.                      render_quad( ctx, i-3, i-2, i-1, i, i );
  1114.                   }
  1115.                }
  1116.             }
  1117.          }
  1118.          else {
  1119.             /* no vertices were clipped */
  1120.             GLuint i;
  1121.             if (ctx->DirectTriangles) {
  1122.                for (i=3;i<VB->Count;i+=4) {
  1123.                   START_PROFILE
  1124.                   (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i );
  1125.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1126.                }
  1127.             }
  1128.             else {
  1129.                for (i=3;i<VB->Count;i+=4) {
  1130.                   render_quad( ctx, i-3, i-2, i-1, i, i );
  1131.                }
  1132.             }
  1133.          }
  1134.          break;
  1135.  
  1136.       case GL_QUAD_STRIP:
  1137.          ASSERT(ctx->Driver.TriangleFunc);
  1138.          ASSERT(ctx->Driver.QuadFunc);
  1139.          if (VB->ClipOrMask) {
  1140.             GLuint i;
  1141.             for (i=3;i<VB->Count;i+=2) {
  1142.                if (VB->ClipMask[i-2] & VB->ClipMask[i-3]
  1143.                    & VB->ClipMask[i-1] & VB->ClipMask[i] & CLIP_ALL_BITS) {
  1144.                   /* all points clipped by common plane */
  1145.                   continue;
  1146.                }
  1147.                else if (VB->ClipMask[i-2] | VB->ClipMask[i-3]
  1148.                         | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  1149.                   vlist[0] = i-1;
  1150.                   vlist[1] = i-3;
  1151.                   vlist[2] = i-2;
  1152.                   vlist[3] = i-0;
  1153.                   render_clipped_polygon( ctx, 4, vlist );
  1154.                }
  1155.                else {
  1156.                   if (ctx->DirectTriangles) {
  1157.                      START_PROFILE
  1158.                      (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i );
  1159.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1160.                   }
  1161.                   else {
  1162.                      render_quad( ctx, i-3, i-2, i, i-1, i );
  1163.                   }
  1164.                }
  1165.             }
  1166.          }
  1167.          else {
  1168.             /* no clipping needed */
  1169.             GLuint i;
  1170.             if (ctx->DirectTriangles) {
  1171.                for (i=3;i<VB->Count;i+=2) {
  1172.                   START_PROFILE
  1173.                   (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i );
  1174.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1175.                }
  1176.             }
  1177.             else {
  1178.                for (i=3;i<VB->Count;i+=2) {
  1179.                   render_quad( ctx, i-3, i-2, i, i-1, i );
  1180.                }
  1181.             }
  1182.          }
  1183.          break;
  1184.  
  1185.       case GL_POLYGON:
  1186.          ASSERT(ctx->Driver.TriangleFunc);
  1187.          if (VB->Count>2) {
  1188.             if (VB->ClipAndMask & CLIP_ALL_BITS) {
  1189.                /* all points clipped by common plane, draw nothing */
  1190.                break;
  1191.             }
  1192.             if (VB->ClipOrMask) {
  1193.                /* need clipping */
  1194.                GLuint i;
  1195.                for (i=0;i<VB->Count;i++) {
  1196.                   vlist[i] = i;
  1197.                }
  1198.                render_clipped_polygon( ctx, VB->Count, vlist );
  1199.             }
  1200.             else {
  1201.                /* no clipping needed */
  1202.                static GLuint const_vlist[VB_SIZE];
  1203.                static GLboolean initFlag = GL_TRUE;
  1204.                if (initFlag) {
  1205.                   /* vertex list always the same, never changes */
  1206.                   GLuint i;
  1207.                   for (i=0;i<VB_SIZE;i++) {
  1208.                      const_vlist[i] = i;
  1209.                   }
  1210.                   initFlag = GL_FALSE;
  1211.                }
  1212.                render_polygon( ctx, VB->Count, const_vlist );
  1213.             }
  1214.          }
  1215.          break;
  1216.  
  1217.       default:
  1218.          /* should never get here */
  1219.          gl_problem( ctx, "invalid mode in gl_render_vb" );
  1220.    }
  1221.  
  1222.    gl_reset_vb( ctx, allDone );
  1223. }
  1224.  
  1225.  
  1226. #define CLIP_ALL_BITS    0x3f
  1227.  
  1228.  
  1229. /*
  1230.  * After we've rendered the primitives in the vertex buffer we call
  1231.  * this function to reset the vertex buffer.  That is, we prepare it
  1232.  * for the next batch of vertices.
  1233.  * Input:  ctx - the context
  1234.  *         allDone - GL_TRUE = glEnd() was called
  1235.  *                   GL_FALSE = buffer was filled, more vertices to come
  1236.  */
  1237. void gl_reset_vb( GLcontext *ctx, GLboolean allDone )
  1238. {
  1239.    struct vertex_buffer *VB = ctx->VB;
  1240.  
  1241.    /* save a few VB values for the end of this function */
  1242.    int oldCount = VB->Count;
  1243.    GLubyte clipOrMask = VB->ClipOrMask;
  1244.    GLboolean monoMaterial = VB->MonoMaterial;
  1245.    GLuint vertexSizeMask = VB->VertexSizeMask;
  1246.  
  1247.    /* Special case for GL_LINE_LOOP */
  1248.    if (ctx->Primitive==GL_LINE_LOOP && allDone) {
  1249.       if (VB->ClipMask[VB->Count-1] | VB->ClipMask[0]) {
  1250.          render_clipped_line( ctx, VB->Count-1, 0 );
  1251.       }
  1252.       else {
  1253.          START_PROFILE
  1254. #ifdef DEBUG
  1255.          debug_line();
  1256. #endif
  1257.          (*ctx->Driver.LineFunc)( ctx, VB->Count-1, 0, 0 );
  1258.          END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  1259.       }
  1260.    }
  1261.  
  1262.    if (allDone) {
  1263.       /* glEnd() was called so reset Vertex Buffer to default, empty state */
  1264.       VB->Start = VB->Count = 0;
  1265.       VB->ClipOrMask = 0;
  1266.       VB->ClipAndMask = CLIP_ALL_BITS;
  1267.       VB->MonoMaterial = GL_TRUE;
  1268.       VB->MonoNormal = GL_TRUE;
  1269.       VB->MonoColor = GL_TRUE;
  1270.       VB->VertexSizeMask = VERTEX3_BIT;
  1271.       if (VB->TexCoordSize!=2) {
  1272.          GLint i, n = VB->Count;
  1273.          for (i=0;i<n;i++) {
  1274.             VB->TexCoord[i][2] = 0.0F;
  1275.             VB->TexCoord[i][3] = 1.0F;
  1276.          }
  1277.       }
  1278.       if (ctx->Current.TexCoord[2]==0.0F && ctx->Current.TexCoord[3]==1.0F) {
  1279.          VB->TexCoordSize = 2;
  1280.       }
  1281.       else {
  1282.          VB->TexCoordSize = 4;
  1283.       }
  1284.    }
  1285.    else {
  1286.       /* The vertex buffer was filled but we didn't get a glEnd() call yet
  1287.        * have to "re-cycle" the vertex buffer.
  1288.        */
  1289.       switch (ctx->Primitive) {
  1290.          case GL_POINTS:
  1291.             ASSERT(VB->Start==0);
  1292.             VB->Start = VB->Count = 0;
  1293.             VB->ClipOrMask = 0;
  1294.             VB->ClipAndMask = CLIP_ALL_BITS;
  1295.             VB->MonoMaterial = GL_TRUE;
  1296.             VB->MonoNormal = GL_TRUE;
  1297.             break;
  1298.          case GL_LINES:
  1299.             ASSERT(VB->Start==0);
  1300.             VB->Start = VB->Count = 0;
  1301.             VB->ClipOrMask = 0;
  1302.             VB->ClipAndMask = CLIP_ALL_BITS;
  1303.             VB->MonoMaterial = GL_TRUE;
  1304.             VB->MonoNormal = GL_TRUE;
  1305.             break;
  1306.          case GL_LINE_STRIP:
  1307.             copy_vertex( VB, 0, VB->Count-1 );  /* copy last vertex to front */
  1308.             VB->Start = VB->Count = 1;
  1309.             VB->ClipOrMask = VB->ClipMask[0];
  1310.             VB->ClipAndMask = VB->ClipMask[0];
  1311.             VB->MonoMaterial = VB->MaterialMask[0] ? GL_FALSE : GL_TRUE;
  1312.             break;
  1313.          case GL_LINE_LOOP:
  1314.             ASSERT(VB->Count==VB_MAX);
  1315.             copy_vertex( VB, 1, VB_MAX-1 );
  1316.             VB->Start = VB->Count = 2;
  1317.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1318.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1319.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1320.             break;
  1321.          case GL_TRIANGLES:
  1322.             ASSERT(VB->Start==0);
  1323.             VB->Start = VB->Count = 0;
  1324.             VB->ClipOrMask = 0;
  1325.             VB->ClipAndMask = CLIP_ALL_BITS;
  1326.             VB->MonoMaterial = GL_TRUE;
  1327.             VB->MonoNormal = GL_TRUE;
  1328.             break;
  1329.          case GL_TRIANGLE_STRIP:
  1330.             copy_vertex( VB, 0, VB_MAX-2 );
  1331.             copy_vertex( VB, 1, VB_MAX-1 );
  1332.             VB->Start = VB->Count = 2;
  1333.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1334.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1335.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1336.             break;
  1337.          case GL_TRIANGLE_FAN:
  1338.             copy_vertex( VB, 1, VB_MAX-1 );
  1339.             VB->Start = VB->Count = 2;
  1340.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1341.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1342.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1343.             break;
  1344.          case GL_QUADS:
  1345.             ASSERT(VB->Start==0);
  1346.             VB->Start = VB->Count = 0;
  1347.             VB->ClipOrMask = 0;
  1348.             VB->ClipAndMask = CLIP_ALL_BITS;
  1349.             VB->MonoMaterial = GL_TRUE;
  1350.             VB->MonoNormal = GL_TRUE;
  1351.             break;
  1352.          case GL_QUAD_STRIP:
  1353.             copy_vertex( VB, 0, VB_MAX-2 );
  1354.             copy_vertex( VB, 1, VB_MAX-1 );
  1355.             VB->Start = VB->Count = 2;
  1356.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1357.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1358.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1359.             break;
  1360.          case GL_POLYGON:
  1361.             copy_vertex( VB, 1, VB_MAX-1 );
  1362.             VB->Start = VB->Count = 2;
  1363.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1364.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1365.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1366.             break;
  1367.          default:
  1368.             /* should never get here */
  1369.             gl_problem(ctx, "Bad primitive type in gl_reset_vb()");
  1370.       }
  1371.    }
  1372.  
  1373.    if (clipOrMask) {
  1374.       /* reset clip masks to zero */
  1375.       MEMSET( VB->ClipMask + VB->Start, 0,
  1376.               (oldCount - VB->Start) * sizeof(VB->ClipMask[0]) );
  1377.    }
  1378.  
  1379.    if (!monoMaterial) {
  1380.       /* reset material masks to zero */
  1381.       MEMSET( VB->MaterialMask + VB->Start, 0,
  1382.               (oldCount - VB->Start) * sizeof(VB->MaterialMask[0]) );
  1383.       gl_update_lighting(ctx);
  1384.    }
  1385.  
  1386.    if (vertexSizeMask!=VERTEX3_BIT) {
  1387.       /* reset object W coords to one */
  1388.       GLint i, n;
  1389.       GLfloat (*obj)[4] = VB->Obj + VB->Start;
  1390.       n = oldCount - VB->Start;
  1391.       for (i=0; i<n; i++) {
  1392.          obj[i][3] = 1.0F;
  1393.       }
  1394.    }
  1395. }
  1396.